package dsx.rpcProxy;

import dsx.config.Config;
import dsx.config.ConfigItem;
import dsx.console.DsxConsole;
import dsx.inf.IConverter;
import dsx.inf.INetProxy;
import dsx.inf.ISlicer;
import dsx.log.ServLog;
import dsx.iot._IotData;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class RPCProxyIot {

    INetProxy netProxy = null;
    ISlicer slicer = null;
    IConverter converter = null;

    static int status = 0; // 状态：0 关闭，1 启动
    static HashMap<String, RPCProxyIot> proxyMap = new HashMap<>();

    public static void start() {
        synchronized (proxyMap) {
            if (status != 0)
                return;
            ArrayList<_RPCProxy> configs = loadConfig();
            for (_RPCProxy config : configs) {
                try {
                    RPCProxyIot proxy = new RPCProxyIot();
                    if (config.slicerClass.equals(""))
                        proxy.slicer = null;
                    else
                        proxy.slicer = (ISlicer) Class.forName(
                                config.slicerClass).newInstance();
                    proxy.converter = (IConverter) Class.forName(
                            config.converterClass).newInstance();
                    proxy.netProxy = (INetProxy) Class.forName(
                            config.netProxyClass).newInstance();
                    proxy.netProxy.start(config.netProxyName, proxy.slicer,
                            proxy.converter);
                    proxyMap.put(config.proxyName, proxy);
                } catch (Exception ex) {
                    DsxConsole.out(ex.getMessage(), "rpcProxy", ServLog.error);
                }
            }
            status = 1;
        }
    }

    public static Object request(String proxyName, Object reqObj, String inf, String src,
                                 Class<?> answType) {
        if (status == 0)
            start();
        RPCProxyIot proxy = null;
        synchronized (proxyMap) {
            proxy = proxyMap.get(proxyName);
        }
        if (proxy == null)
            return null;
        try {
            _IotData req = newIotData(src, inf);
            req.setParam(reqObj);
            _IotData iotData = (_IotData) proxy.netProxy.request(req, _IotData.class);
            return proxy.converter.toObject(proxy.converter.toString(iotData.getParam()), answType);
        } catch (Exception ex) {
            return null;
        }
    }

    public static Object request(String proxyName, Object reqObj, String inf, String src,
                                 Class<?> answType, String host, int port) {
        if (status == 0)
            start();
        RPCProxyIot proxy = null;
        synchronized (proxyMap) {
            proxy = proxyMap.get(proxyName);
        }
        if (proxy == null)
            return null;
        try {
            _IotData req = newIotData(src, inf);
            req.setParam(reqObj);
            _IotData iotData = (_IotData) proxy.netProxy.request(req, _IotData.class, host, port);
            return proxy.converter.toObject(proxy.converter.toString(iotData.getParam()), answType);
        } catch (Exception ex) {
            return null;
        }
    }

    public static void stop() {
        synchronized (proxyMap) {
            if (status == 0)
                return;
            for (Map.Entry<String, RPCProxyIot> entry : proxyMap.entrySet()) {
                try {
                    entry.getValue().netProxy.stop();
                } catch (Exception ex) {
                }
            }
            proxyMap.clear();
        }
    }

    private static ArrayList<_RPCProxy> loadConfig() {
        ArrayList<_RPCProxy> ret = new ArrayList<_RPCProxy>();
        try {
            ArrayList<ArrayList<ConfigItem>> sections = Config
                    .getSections("RPCProxy");
            for (int i = 0; i < sections.size(); i++) {
                ArrayList<ConfigItem> fields = sections.get(i);
                _RPCProxy config = new _RPCProxy();
                for (int j = 0; j < fields.size(); j++) {
                    ConfigItem field = fields.get(j);
                    switch (field.name) {
                        case "proxyName":
                            config.setProxyName(field.value);
                            break;
                        case "converterClass":
                            config.setConverterClass(field.value);
                            break;
                        case "slicerClass":
                            config.setSlicerClass(field.value);
                            break;
                        case "netProxyName":
                            config.setNetProxyName(field.value);
                            break;
                        case "netProxyClass":
                            config.setNetProxyClass(field.value);
                            break;
                    }
                }
                ret.add(config);
            }
        } catch (Exception ex) {
            DsxConsole.out(ex.getMessage(), "rpcProxy", ServLog.error);
        }
        return ret;
    }

    private static _IotData newIotData(String src, String inf) {
        _IotData iotData = new _IotData();
        iotData.setType(0);
        iotData.setAuth("");
        iotData.setSrc(src);
        iotData.setInf(inf);
        iotData.setFlag(Long.toString(new Date().getTime()));
        iotData.setParam(null);
        return iotData;
    }

}
